﻿// CDlgRebarLib.cpp: 实现文件
//

#include "Stdafx.h"
#include "CDlgRebarLib.h"
#include "afxdialogex.h"
#include <numeric>
#include <filesystem>
#include <fstream>
#include "configor/json.hpp"
#include "Conver.h"

#include <locale>
#include <codecvt>
#include <string>
#include "Keeper.h"
#include "ArxSelector.h"
#include "McElementRebarExpression.h"
#include "ArxDatabase.h"
#include "CDlgInput.h"

CDlgRebarLib* CDlgRebarLib::s_instance = nullptr;

// CDlgRebarLib 对话框

IMPLEMENT_DYNAMIC(CDlgRebarLib, CDialogEx)

CDlgRebarLib::CDlgRebarLib(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG_REBAR_LIB, pParent)
{

}

CDlgRebarLib::~CDlgRebarLib()
{
}

void CDlgRebarLib::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_REBAR, m_list);
}


BEGIN_MESSAGE_MAP(CDlgRebarLib, CDialogEx)
	ON_MESSAGE(WM_ACAD_KEEPFOCUS, OnAcadKeepFocus)
	ON_BN_CLICKED(IDC_BUTTON_REFRESH, &CDlgRebarLib::OnBnClickedButtonRefresh)
	ON_BN_CLICKED(IDC_BUTTON_CALL, &CDlgRebarLib::OnBnClickedButtonCall)
	ON_BN_CLICKED(IDC_BUTTON_DEL, &CDlgRebarLib::OnBnClickedButtonDel)
	ON_NOTIFY(NM_DBLCLK, IDC_LIST_REBAR, &CDlgRebarLib::OnNMDblclkListRebar)
END_MESSAGE_MAP()


// CDlgRebarLib 消息处理程序

CDlgRebarLib* CDlgRebarLib::GetInstance()
{
	if (s_instance == nullptr)
	{
		s_instance = new CDlgRebarLib();
		s_instance->Create(IDD_DIALOG_REBAR_LIB, acedGetAcadFrame());
	}

	return s_instance;
}

LRESULT CDlgRebarLib::OnAcadKeepFocus(WPARAM, LPARAM)
{
	return TRUE;
}

BOOL CDlgRebarLib::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	InitRebarList();
	// TODO:  在此添加额外的初始化

	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

void CDlgRebarLib::InitRebarList()
{
	while (m_list.DeleteColumn(0)) {}
	m_list.DeleteAllItems();

	CString columnNames[] = { _T("序号"), _T("代号"), _T("路径") };

	CRect rc;
	m_list.GetWindowRect(rc);
	int width = rc.Width() - 5;

	int	columnWeights[] = { 1 ,3,5 };
	int weight = std::accumulate(std::begin(columnWeights), std::end(columnWeights), 0);

	m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

	for (int i = 0; i < CT_COUNT; ++i)
	{
		m_list.InsertColumn(i, columnNames[i], 0, columnWeights[i] * (width / weight));
	}

	RefreshListData();
}

void CDlgRebarLib::RefreshListData()
{
	m_list.DeleteAllItems();

	LoadRebarData();

	int index = 0;

	for (auto pair : m_rebarPathMap)
	{
		auto pRebarData = pair.first;

		AcString name;

		int row = m_list.InsertItem(index++, _T(""));

		CString sNo;
		sNo.Format(_T("%d"), row + 1);

		m_list.SetItemText(row, CT_REBAR_NO, sNo);
		m_list.SetItemText(row, CT_REBAR_CODE, pRebarData->code);
		m_list.SetItemText(row, CT_REBAR_PATH, pair.second);

		m_list.SetItemData(row, (DWORD_PTR)pRebarData);
	}
}

void CDlgRebarLib::LoadRebarData()
{
	for (auto pair : m_rebarPathMap)
	{
		delete pair.first;
	}

	m_rebarPathMap.clear();

	if (!std::filesystem::exists(RebarLibPath))
	{
		return;
	}

	std::filesystem::path libPath(RebarLibPath);

	for (const std::filesystem::directory_entry & item : std::filesystem::directory_iterator(libPath))
	{
		if (item.path().extension().wstring() == _T(".json"))
		{
			std::locale oNewLocale(std::locale(), "", std::locale::ctype);
			std::locale oPreviousLocale = std::locale::global(oNewLocale);

			std::wifstream ifs(item.path().wstring());

			if (ifs.is_open())
			{
				try
				{
					configor::wjson wj;
					ifs >> wj;

					McRebarDetailData* pData = new McRebarDetailData();

					if (Conver::Json2McRebarDetailData(wj, *pData))
					{
						m_rebarPathMap[pData] = item.path().wstring().c_str();
					}
					else
					{
						delete pData;
					}
				}
				catch(...)
				{
					
				}

				ifs.close();
			}

			std::locale::global(oPreviousLocale);
		}
	}
}

void CDlgRebarLib::OnBnClickedButtonRefresh()
{
	RefreshListData();
}


void CDlgRebarLib::OnBnClickedButtonCall()
{
	int item = GetSelectedItem();

	if (item >= 0)
	{
		auto pData = (McRebarDetailData*)m_list.GetItemData(item);
		CallRebar(*pData);
	}
}

void CDlgRebarLib::CallRebar(const McRebarDetailData& data)
{
	McRebarExpressionVar expressionVar;

	std::vector<CString> varNames;

	data.GetVarNames(varNames);

	for (auto var : varNames)
	{
		CString sPrompt;
		sPrompt.Format(_T("\n请指定变量<%s>的值："), var.GetString());

		CString sContent;
		if (!CDlgInput::GetInput(this, sPrompt, sContent))
		{
			return;
		}

		double value = _ttof(sContent);

		expressionVar.vars[var.GetString()] = value;
	}

	Keeper&& _keeper = Disposable::ProvisionalHide(this->GetParentOwner());

	AcGePoint3d basePoint;

	if (CArxSelector::GetCurrentDocSelector().GetPoint(_T("\n请指定插入基点:"), basePoint))
	{
		AcDbObjectIdArray rebarIds;

		CArxDatabase::GetCurrentDatabase().DrawRebar(basePoint, data, expressionVar, rebarIds);
	}
}

void CDlgRebarLib::OnBnClickedButtonDel()
{
	int item = GetSelectedItem();

	if (item >= 0)
	{
		auto pData = (McRebarDetailData*)m_list.GetItemData(item);

		std::error_code error;

		if (std::filesystem::remove(m_rebarPathMap[pData].GetString(), error))
		{
			m_list.DeleteItem(item);
			m_rebarPathMap.erase(pData);
			delete pData;
		}
		else
		{
			std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
			CString sMsg;
			sMsg.Format(_T("ErrorCode:%d"), error.value());
			MessageBox(sMsg);
		}
	}

	// TODO: 在此添加控件通知处理程序代码
}

int CDlgRebarLib::GetSelectedItem()
{
	POSITION pos = m_list.GetFirstSelectedItemPosition();

	return m_list.GetNextSelectedItem(pos);
}


void CDlgRebarLib::OnNMDblclkListRebar(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码	int item = GetSelectedItem();

	int item = GetSelectedItem();

	if (item >= 0)
	{
		auto pData = (McRebarDetailData*)m_list.GetItemData(item);
		CallRebar(*pData);
	}

	*pResult = 0;
}
